Conversation
lovelydinosaur
left a comment
There was a problem hiding this comment.
🤩 Let me know at whatever point you need my input on this. Looking good!
|
Hi @tomchristie, I was finally able to finish the first turn around and there're some issues appeared.
Also there might be some confusion as Update: All in all, we just need to distinguish
In overall, it's pretty close to Yeah, it would great to have any feedback, recommendations, complains. |
|
I suppose sqlalchemy should only see it as |
|
Yes, I see, it clarifies and makes it easier. |
|
@tomchristie, @gvbgduh when do you plan to merge this PR? |
|
Yup, it'd be great to get this in! |
|
|
||
|
|
||
| def test_aiopg_ssl(): | ||
| backend = AiopgBackend("postgres+aiopg://localhost/database?ssl=true") |
There was a problem hiding this comment.
Looks like we're expecting postgres+aiopg in some places and postgresql+aiopg in others.
I'd be okay with us accepting either or both.
There was a problem hiding this comment.
Right, yeah, it's a typo, but we only expect postgresql+aiopg as of now, at least there's only this mapping. it's not triggered in these tests as don't make any use of it. I'll update urls to avoid confusion.
| # Apparently for `aiopg` it's OID that will always 0 in this case | ||
| # As it's only one action within this cursor life cycle | ||
| # It's recommended to use the `RETURNING` clause | ||
| # For obtaining the record id |
There was a problem hiding this comment.
This is a good example of where we ought to be returning a more structured type from .execute - that way we could have different drivers either support or not support result.row_id.
There was a problem hiding this comment.
Can we change our query here to make it consistently return the pk across all our implementations maybe?
There was a problem hiding this comment.
Yes, sounds reasonable indeed.
There're two ways though as I can see:
- provide pure driver experience with minimal overhead, hence it'll vary from driver to driver, but will keep it as simple as possible if it can matter, or
- provide unified API and implement the missing bits providing the missing functionality, but allocating the additional overhead
There was a problem hiding this comment.
Oh, just 25 secs later, ok, let's follow the second path, all in all, there's always a way to jump to the raw driver and get the full manual control over it.
There was a problem hiding this comment.
@tomchristie I'm thinking quite hard about it. There's a function in postgres - lastval() that can be executed to retrieve the value, but it's not reliable as there're circumstances where it can return the wrong value. The returning clause is the best way to do it, but we can't assume how the PK column is called and returning * won't be consistent with other back-ends.
| values = {"data": data} | ||
|
|
||
| if database.url.scheme == "postgresql+aiopg": | ||
| await database.execute(query, {"data": json.dumps(data)}) |
There was a problem hiding this comment.
Can we handle this automatically for our users?
Would that be a sensible thing to do here?
There was a problem hiding this comment.
Not sure it's possible in all cases, as I would need to know that the column of a type json, so it'll require either a lookup to the sqlalchemy's metadata or to the DB schema. But I'll have a look at how easy it can be.
There was a problem hiding this comment.
it'll require either a lookup to the sqlalchemy's metadata or to the DB schema
If it means a lookup then let's not do it. I'm just not clear why JSONField isn't already handling the serialization for us in this case. Might need some more looking into?
There was a problem hiding this comment.
yeah, I'm dealing with it now, there're several facets to approach it.
it can work canonically, but the field has to be sqlalchemy.dialects.postgresql.JSON, but aiopg returns back (over select) the decoded value and it breaks the RowProxy as it expects string.
so, i'm looking for compromise/settings to get the balance
There was a problem hiding this comment.
ok, it was the matter of the dialect class, I reused the one that's in use for the integration with sa part of aoipg it got back to normal.
| await cursor.executemany(insert_query, values) | ||
| elif database.url.scheme == "postgresql+aiopg": | ||
| cursor = await raw_connection.cursor() | ||
| # No async support for `executemany` |
There was a problem hiding this comment.
Okay, in these kinds of cases we should still support the .executemany API, even if all it actually does is for value in values: ...execute... under the hood.
(We can document limitations of particular drivers, but it'd def. be a benefit if we can keep the API the same, even if there's different performance characteristics in some cases.)
There was a problem hiding this comment.
Yeah, I see and agree, will try my best.
There was a problem hiding this comment.
Ok, it's the test for the raw driver across different backends, but aiopg has the implementation for execute_many and yeah it's with the for loop.
There was a problem hiding this comment.
Grand, let's just hook our backend implementation up to that then, right?
There was a problem hiding this comment.
All should be in place! I have a unittest to test it for database.execute_many.
There was a problem hiding this comment.
this case is the battle test of the raw driver, so it replicates backend implementations in some places.
| database_url = DatabaseURL(url) | ||
| if database_url.dialect == "mysql": | ||
| url = str(database_url.replace(driver="pymysql")) | ||
| elif database_url.driver == "aiopg": |
There was a problem hiding this comment.
Let's check the .scheme here instead in these conditionals.
|
Yes yes yes! Let's make this a priority. 🚀 |
|
Awesome, thanks @tomchristie! |
|
@tomchristie I think it's in good shape now. There's only one open question - |
|
hi @tomchristie! A gentle nudge here, I think it's mergeable. Happy to follow up on any appeared issues anyway. |
|
What would be the point of this if databases already works with asyncpg? |
|
@StephenCarboni There's a bunch of different reasons, but the main point is |
No description provided.